home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / brightness_contrast.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-29  |  13.7 KB  |  513 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <gtk/gtk.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "brightness_contrast.h"
  27. #include "drawable.h"
  28. #include "gimplut.h"
  29. #include "gimpui.h"
  30. #include "gdisplay.h"
  31. #include "image_map.h"
  32. #include "lut_funcs.h"
  33.  
  34. #include "libgimp/gimpintl.h"
  35.  
  36. #define SLIDER_WIDTH 200
  37.  
  38. #define BRIGHTNESS  0x1
  39. #define CONTRAST    0x2
  40. #define ALL        (BRIGHTNESS | CONTRAST)
  41.  
  42. /*  the brightness-contrast structures  */
  43.  
  44. typedef struct _BrightnessContrast BrightnessContrast;
  45.  
  46. struct _BrightnessContrast
  47. {
  48.   gint x, y;    /*  coords for last mouse click  */
  49. };
  50.  
  51. typedef struct _BrightnessContrastDialog BrightnessContrastDialog;
  52.  
  53. struct _BrightnessContrastDialog
  54. {
  55.   GtkWidget     *shell;
  56.   GtkWidget     *gimage_name;
  57.  
  58.   GtkAdjustment *brightness_data;
  59.   GtkAdjustment *contrast_data;
  60.  
  61.   GimpDrawable  *drawable;
  62.   ImageMap       image_map;
  63.  
  64.   gdouble        brightness;
  65.   gdouble        contrast;
  66.  
  67.   gboolean       preview;
  68.   GimpLut       *lut;
  69.  
  70.   glong          conn_id;
  71. };
  72.  
  73.  
  74. /*  the brightness-contrast tool options  */
  75. static ToolOptions *brightness_contrast_options = NULL;
  76.  
  77. /*  the brightness-contrast dialog  */
  78. static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
  79.  
  80.  
  81. /*  brightness contrast action functions  */
  82.  
  83. static void   brightness_contrast_control (Tool *, ToolAction, gpointer);
  84.  
  85. static BrightnessContrastDialog * brightness_contrast_dialog_new (void);
  86.  
  87. static void   brightness_contrast_update          (BrightnessContrastDialog *,
  88.                            gint);
  89. static void   brightness_contrast_preview         (BrightnessContrastDialog *);
  90. static void   brightness_contrast_reset_callback  (GtkWidget *, gpointer);
  91. static void   brightness_contrast_ok_callback     (GtkWidget *, gpointer);
  92. static void   brightness_contrast_cancel_callback (GtkWidget *, gpointer);
  93. static void   brightness_contrast_preview_update  (GtkWidget *, gpointer);
  94. static void   brightness_contrast_brightness_adjustment_update (GtkAdjustment *,
  95.                                 gpointer);
  96. static void   brightness_contrast_contrast_adjustment_update   (GtkAdjustment *,
  97.                                 gpointer);
  98.  
  99. /*  brightness-contrast select action functions  */
  100.  
  101. static void
  102. brightness_contrast_control (Tool       *tool,
  103.                  ToolAction  action,
  104.                  gpointer    gdisp_ptr)
  105. {
  106.   switch (action)
  107.     {
  108.     case PAUSE:
  109.       break;
  110.  
  111.     case RESUME:
  112.       break;
  113.  
  114.     case HALT:
  115.       brightness_contrast_dialog_hide ();
  116.       break;
  117.  
  118.     default:
  119.       break;
  120.     }
  121. }
  122.  
  123. Tool *
  124. tools_new_brightness_contrast (void)
  125. {
  126.   Tool * tool;
  127.   BrightnessContrast * private;
  128.  
  129.   /*  The tool options  */
  130.   if (!brightness_contrast_options)
  131.     {
  132.       brightness_contrast_options =
  133.     tool_options_new (_("Brightness-Contrast"));
  134.       tools_register (BRIGHTNESS_CONTRAST, brightness_contrast_options);
  135.    }
  136.  
  137.   tool = tools_new_tool (BRIGHTNESS_CONTRAST);
  138.   private = g_new0 (BrightnessContrast, 1);
  139.  
  140.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  141.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  142.  
  143.   tool->private = (void *) private;
  144.  
  145.   tool->control_func = brightness_contrast_control;
  146.  
  147.   return tool;
  148. }
  149.  
  150. void
  151. brightness_contrast_dialog_hide (void)
  152. {
  153.   if (brightness_contrast_dialog)
  154.     brightness_contrast_cancel_callback (NULL,
  155.                                      (gpointer) brightness_contrast_dialog);
  156.   
  157. void
  158. tools_free_brightness_contrast (Tool *tool)
  159. {
  160.   BrightnessContrast * bc;
  161.  
  162.   bc = (BrightnessContrast *) tool->private;
  163.  
  164.   /*  Close the brightness-contrast dialog  */
  165.   brightness_contrast_dialog_hide ();
  166.  
  167.   g_free (bc);
  168. }
  169.  
  170. void
  171. brightness_contrast_initialize (GDisplay *gdisp)
  172. {
  173.   if (gimp_image_is_empty (gdisp->gimage))
  174.     {
  175.       g_message (_("The image has no drawables."));
  176.       return;
  177.     }
  178.  
  179.   if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
  180.     {
  181.       g_message (_("Brightness-Contrast does not operate on indexed drawables."));
  182.       return;
  183.     }
  184.  
  185.   /*  The brightness-contrast dialog  */
  186.   if (!brightness_contrast_dialog)
  187.     brightness_contrast_dialog = brightness_contrast_dialog_new ();
  188.   else
  189.     if (!GTK_WIDGET_VISIBLE (brightness_contrast_dialog->shell))
  190.       gtk_widget_show (brightness_contrast_dialog->shell);
  191.  
  192.   brightness_contrast_dialog->brightness = 0.0;
  193.   brightness_contrast_dialog->contrast   = 0.0;
  194.  
  195.   brightness_contrast_dialog->drawable = gimage_active_drawable (gdisp->gimage);
  196.   brightness_contrast_dialog->image_map =
  197.     image_map_create (gdisp, brightness_contrast_dialog->drawable);
  198.  
  199.   brightness_contrast_update (brightness_contrast_dialog, ALL);
  200.  
  201.   /* Merge-related undo release signal */
  202.  
  203.   brightness_contrast_dialog->conn_id = 
  204.     gtk_signal_connect (GTK_OBJECT (gdisp->gimage), "layer_merge",
  205.             GTK_SIGNAL_FUNC (brightness_contrast_cancel_callback),
  206.             brightness_contrast_dialog);
  207. }
  208.  
  209. /********************************/
  210. /*  Brightness Contrast dialog  */
  211. /********************************/
  212.  
  213. static BrightnessContrastDialog *
  214. brightness_contrast_dialog_new (void)
  215. {
  216.   BrightnessContrastDialog *bcd;
  217.   GtkWidget *vbox;
  218.   GtkWidget *hbox;
  219.   GtkWidget *table;
  220.   GtkWidget *label;
  221.   GtkWidget *abox;
  222.   GtkWidget *spinbutton;
  223.   GtkWidget *slider;
  224.   GtkWidget *toggle;
  225.   GtkObject *data;
  226.  
  227.   bcd = g_new (BrightnessContrastDialog, 1);
  228.   bcd->preview = TRUE;
  229.  
  230.   bcd->lut = gimp_lut_new ();
  231.  
  232.   /*  The shell and main vbox  */
  233.   bcd->shell =
  234.     gimp_dialog_new (_("Brightness-Contrast"), "brightness_contrast",
  235.              tools_help_func, NULL,
  236.              GTK_WIN_POS_NONE,
  237.              FALSE, TRUE, FALSE,
  238.  
  239.              _("OK"), brightness_contrast_ok_callback,
  240.              bcd, NULL, NULL, TRUE, FALSE,
  241.              _("Reset"), brightness_contrast_reset_callback,
  242.              bcd, NULL, NULL, TRUE, FALSE,
  243.              _("Cancel"), brightness_contrast_cancel_callback,
  244.              bcd, NULL, NULL, FALSE, TRUE,
  245.  
  246.              NULL);
  247.  
  248.   vbox = gtk_vbox_new (FALSE, 4);
  249.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  250.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (bcd->shell)->vbox), vbox);
  251.  
  252.   /*  The table containing sliders  */
  253.   table = gtk_table_new (2, 3, FALSE);
  254.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  255.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  256.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  257.  
  258.   /*  Create the brightness scale widget  */
  259.   label = gtk_label_new (_("Brightness:"));
  260.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  261.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
  262.             GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  263.  
  264.   data = gtk_adjustment_new (0, -127, 127.0, 1.0, 10.0, 0.0);
  265.   bcd->brightness_data = GTK_ADJUSTMENT (data);
  266.   slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
  267.   gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
  268.   gtk_scale_set_digits (GTK_SCALE (slider), 0);
  269.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  270.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  271.   gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1);
  272.  
  273.   abox = gtk_vbox_new (FALSE, 0);
  274.   spinbutton = gtk_spin_button_new (bcd->brightness_data, 1.0, 0);
  275.   gtk_widget_set_usize (spinbutton, 75, -1);
  276.   gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
  277.   gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1,
  278.             GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  279.  
  280.   gtk_signal_connect (GTK_OBJECT (data), "value_changed",
  281.               GTK_SIGNAL_FUNC (brightness_contrast_brightness_adjustment_update),
  282.               bcd);
  283.  
  284.   gtk_widget_show (label);
  285.   gtk_widget_show (slider);
  286.   gtk_widget_show (spinbutton);
  287.   gtk_widget_show (abox);
  288.  
  289.   /*  Create the contrast scale widget  */
  290.   label = gtk_label_new (_("Contrast:"));
  291.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  292.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
  293.             GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  294.  
  295.   data = gtk_adjustment_new (0, -127.0, 127.0, 1.0, 10.0, 0.0);
  296.   bcd->contrast_data = GTK_ADJUSTMENT (data);
  297.   slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
  298.   gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
  299.   gtk_scale_set_digits (GTK_SCALE (slider), 0);
  300.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  301.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  302.   gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2);
  303.  
  304.   abox = gtk_vbox_new (FALSE, 0);
  305.   spinbutton = gtk_spin_button_new (bcd->contrast_data, 1.0, 0);
  306.   gtk_widget_set_usize (spinbutton, 75, -1);
  307.   gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
  308.   gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2,
  309.             GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
  310.  
  311.   gtk_signal_connect (GTK_OBJECT (data), "value_changed",
  312.               GTK_SIGNAL_FUNC (brightness_contrast_contrast_adjustment_update),
  313.               bcd);
  314.  
  315.   gtk_widget_show (label);
  316.   gtk_widget_show (slider);
  317.   gtk_widget_show (spinbutton);
  318.   gtk_widget_show (abox);
  319.  
  320.   /*  Horizontal box for preview toggle button  */
  321.   hbox = gtk_hbox_new (FALSE, 4);
  322.   gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  323.  
  324.   /*  The preview toggle  */
  325.   toggle = gtk_check_button_new_with_label (_("Preview"));
  326.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bcd->preview);
  327.   gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
  328.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  329.               GTK_SIGNAL_FUNC (brightness_contrast_preview_update),
  330.               bcd);
  331.  
  332.   gtk_widget_show (toggle);
  333.   gtk_widget_show (hbox);
  334.  
  335.   gtk_widget_show (table);
  336.   gtk_widget_show (vbox);
  337.   gtk_widget_show (bcd->shell);
  338.  
  339.   return bcd;
  340. }
  341.  
  342. static void
  343. brightness_contrast_update (BrightnessContrastDialog *bcd,
  344.                 gint                      update)
  345. {
  346.   if (update & BRIGHTNESS)
  347.     {
  348.       gtk_adjustment_set_value (bcd->brightness_data, bcd->brightness);
  349.     }
  350.   if (update & CONTRAST)
  351.     {
  352.       gtk_adjustment_set_value (bcd->contrast_data, bcd->contrast);
  353.     }
  354. }
  355.  
  356. static void
  357. brightness_contrast_preview (BrightnessContrastDialog *bcd)
  358. {
  359.   if (!bcd->image_map)
  360.     {
  361.       g_message ("brightness_contrast_preview(): No image map");
  362.       return;
  363.     }
  364.  
  365.   active_tool->preserve = TRUE;
  366.   brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0,
  367.                  bcd->contrast / 127.0,
  368.                  gimp_drawable_bytes (bcd->drawable));
  369.   image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  370.            (void *) bcd->lut);
  371.   active_tool->preserve = FALSE;
  372. }
  373.  
  374. static void
  375. brightness_contrast_reset_callback (GtkWidget *widget,
  376.                     gpointer   data)
  377. {
  378.   BrightnessContrastDialog *bcd;
  379.  
  380.   bcd = (BrightnessContrastDialog *) data;
  381.  
  382.   bcd->brightness = 0.0;
  383.   bcd->contrast   = 0.0;
  384.  
  385.   brightness_contrast_update (bcd, ALL);
  386.  
  387.   if (bcd->preview)
  388.     brightness_contrast_preview (bcd);
  389. }
  390.  
  391. static void
  392. brightness_contrast_ok_callback (GtkWidget *widget,
  393.                  gpointer   data)
  394. {
  395.   BrightnessContrastDialog *bcd;
  396.  
  397.   bcd = (BrightnessContrastDialog *) data;
  398.  
  399.   gimp_dialog_hide (bcd->shell);
  400.  
  401.   active_tool->preserve = TRUE;
  402.  
  403.   if (!bcd->preview)
  404.   {
  405.     brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0,
  406.                    bcd->contrast / 127.0,
  407.                    gimp_drawable_bytes (bcd->drawable));
  408.     image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  409.              (void *) bcd->lut);
  410.   }
  411.  
  412.   if (bcd->image_map)
  413.     image_map_commit (bcd->image_map);
  414.  
  415.   active_tool->preserve = FALSE;
  416.  
  417.   bcd->image_map = NULL;
  418.  
  419.   active_tool->gdisp_ptr = NULL;
  420.   active_tool->drawable = NULL;
  421. }
  422.  
  423. static void
  424. brightness_contrast_cancel_callback (GtkWidget *widget,
  425.                      gpointer   data)
  426. {
  427.   BrightnessContrastDialog *bcd;
  428.  
  429.   bcd = (BrightnessContrastDialog *) data;
  430.  
  431.   gimp_dialog_hide (bcd->shell);
  432.  
  433.   if (bcd->image_map)
  434.     {
  435.       active_tool->preserve = TRUE;
  436.       image_map_abort (bcd->image_map);
  437.       active_tool->preserve = FALSE;
  438.  
  439.       bcd->image_map = NULL;
  440.       gdisplays_flush ();
  441.     }
  442.  
  443.   if (bcd->conn_id != 0)
  444.     {
  445.       gtk_signal_disconnect (GTK_OBJECT (gimp_drawable_gimage (bcd->drawable)), bcd->conn_id);
  446.       bcd->conn_id = 0;
  447.     }
  448.  
  449.   active_tool->gdisp_ptr = NULL;
  450.   active_tool->drawable = NULL;
  451. }
  452.  
  453. static void
  454. brightness_contrast_preview_update (GtkWidget *widget,
  455.                     gpointer   data)
  456. {
  457.   BrightnessContrastDialog *bcd;
  458.  
  459.   bcd = (BrightnessContrastDialog *) data;
  460.  
  461.   if (GTK_TOGGLE_BUTTON (widget)->active)
  462.     {
  463.       bcd->preview = TRUE;
  464.       brightness_contrast_preview (bcd);
  465.     }
  466.   else
  467.     {
  468.       bcd->preview = FALSE;
  469.       if (bcd->image_map)
  470.     {
  471.       active_tool->preserve = TRUE;
  472.       image_map_clear (bcd->image_map);
  473.       active_tool->preserve = FALSE;
  474.       gdisplays_flush ();
  475.     }
  476.     }
  477. }
  478.  
  479. static void
  480. brightness_contrast_brightness_adjustment_update (GtkAdjustment *adjustment,
  481.                           gpointer       data)
  482. {
  483.   BrightnessContrastDialog *bcd;
  484.  
  485.   bcd = (BrightnessContrastDialog *) data;
  486.  
  487.   if (bcd->brightness != adjustment->value)
  488.     {
  489.       bcd->brightness = adjustment->value;
  490.  
  491.       if (bcd->preview)
  492.     brightness_contrast_preview (bcd);
  493.     }
  494. }
  495.  
  496. static void
  497. brightness_contrast_contrast_adjustment_update (GtkAdjustment *adjustment,
  498.                         gpointer       data)
  499. {
  500.   BrightnessContrastDialog *bcd;
  501.  
  502.   bcd = (BrightnessContrastDialog *) data;
  503.  
  504.   if (bcd->contrast != adjustment->value)
  505.     {
  506.       bcd->contrast = adjustment->value;
  507.  
  508.       if (bcd->preview)
  509.     brightness_contrast_preview (bcd);
  510.     }
  511. }
  512.